package com.sinai.mshab.client.ui.basic;

import java.util.Date;
import java.util.Iterator;

import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.KeyboardListenerAdapter;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.sinai.mshab.client.util.Answer;
import com.sinai.mshab.client.ui.aggregate.DataReceiver;
import com.sinai.mshab.client.ui.aggregate.FormData;
import com.sinai.mshab.client.ui.validate.DateValidator;
import com.thapar.gwt.user.ui.client.widget.simpledatepicker.SimpleDatePicker;
import com.thapar.gwt.user.ui.client.util.*;

/**
 * A composite containing 4 widgets in one horizontal panel. | Description Label |
 * Date Box | Quantifier label | Error Message | Example: | When were you born?
 * |__11/11/1911__| additional text | Error: Please enter a valid date. |
 * 
 * @author serge
 * 
 */
public class DateQuestionComponent extends QuestionComponent {

	private String error_msg = "Please enter the date in the yyyy-mm-dd format";

	/**
	 * Creates a new DateQuestionComponent with no labels and sets a default
	 * quantifier to "(yyyy-mm-dd)".
	 * 
	 * @param dbfieldName
	 *            the name of the field to which the date information
	 *            corresponds to.
	 * @param tableName
	 *            the name of the database table where the date information will
	 *            be stored.
	 */
	public DateQuestionComponent(String dbfieldName, String tableName) {
		initializeWidget(dbfieldName, tableName, null, null,
				error_msg, true);
	}

	/**
	 * Creates a new DateQuestionComponent and sets a default quantifier to
	 * "(yyyy-mm-dd)".
	 * 
	 * @param dbfieldName
	 *            the name of the field to which the textbox information
	 *            corresponds to.
	 * @param description
	 *            The description label that goes before textbox (eg. Name)
	 */
	public DateQuestionComponent(String dbfieldName, String tableName,
			String description) {
		initializeWidget(dbfieldName, tableName, description, "(yyyy-mm-dd)",
				error_msg, true);
	}

	public DateQuestionComponent(String dbfieldName, String tableName,
			String description, boolean horizontal) {
		initializeWidget(dbfieldName, tableName, description, "(yyyy-mm-dd)",
				error_msg, horizontal);
	}

	/**
	 * Creates a new DateQuestionComponent.
	 * 
	 * @param dbfieldName
	 *            the name of the field to which the textbox information
	 *            corresponds to.
	 * @param tableName
	 *            the name of the database table where the textbox information
	 *            will be stored.
	 * @param description
	 *            The description label that goes before textbox (eg. Name)
	 * @param quantifier
	 *            The quantifier label that goes after textbox (eg. /years)
	 */
	public DateQuestionComponent(String dbfieldName, String tableName,
			String description, String quantifier) {
		initializeWidget(dbfieldName, tableName, description, quantifier,
				error_msg, true);
	}

	public DateQuestionComponent(String dbfieldName, String tableName,
			String description, String quantifier, boolean horizontal) {
		initializeWidget(dbfieldName, tableName, description, quantifier,
				error_msg, horizontal);
	}

	/**
	 * Creates a new DateQuestionComponent.
	 * 
	 * @param dbfieldName
	 *            the name of the field to which the textbox information
	 *            corresponds to.
	 * @param tableName
	 *            the name of the database table where the textbox information
	 *            will be stored.
	 * @param description
	 *            The description label that goes before textbox (eg. Name)
	 * @param quantifier
	 *            The quantifier label that goes after textbox (eg. /years)
	 * @param error_msg
	 *            The error message that gets displayed if the attached
	 *            validators do not pass
	 */
	public DateQuestionComponent(String dbfieldName, String tableName,
			String description, String quantifier, String error_msg) {
		initializeWidget(dbfieldName, tableName, description, quantifier,
				error_msg, true);
	}

	public DateQuestionComponent(String dbfieldName, String tableName,
			String description, String quantifier, String error_msg,
			boolean horizontal) {
		initializeWidget(dbfieldName, tableName, description, quantifier,
				error_msg, horizontal);
	}

	/**
	 * Helper method in creating a new <code>DateQuestionComponent</code>.
	 * This allows for us to have one central method for creating a
	 * <code>DateQuestionComponent</code> even though we take in a different
	 * number of parameters.
	 * 
	 * @param dbfieldName
	 *            the name of the field to which the textbox information
	 *            corresponds to.s to.
	 * @param tableName
	 *            the name of the database table where the textbox information
	 *            will be stored.
	 * @param description
	 *            The description label that goes before textbox (eg. Name)
	 * @param quantifier
	 *            The quantifier label that goes after textbox (eg. /years)
	 * @param error_msg
	 *            The error message that gets displayed if the attached
	 *            validators do not pass
	 */
	protected void initializeWidget(String dbfieldName, String tableName,
			String description, String quantifier, String error_msg,
			boolean horizontal) {

		SimpleDatePicker datePicker = new SimpleDatePicker();

		// set he date format
		datePicker.setDateFormat(DateFormat.DATE_FORMAT_YYYYMMDD);
		datePicker.setWeekendSelectable(true);
		datePicker.addClickListener(new MyListener());

		datePicker.setStyleName("gwt-TextBox");

		// adding a new mask and validator
		setMask(new Mask("mmmm-mm-mm"));
		setValidator(new DateValidator());

		// adding keylistener to the date picker
		datePicker.addKeyboardListener(new ValidationKeyboardListener());
		datePicker.addFocusListener(this);

		super.initialize(dbfieldName, tableName, description, quantifier,
				error_msg, datePicker, horizontal);
	}

	/**
	 */
	public void sendAnswer(DataReceiver receiver) {
		String date = ((SimpleDatePicker) widget).getText();

		Answer answer = new Answer();
		answer.add(dbfieldName, tableName, date);
		answer.add(hiddenFields);
		receiver.sendData(answer);
	}

	public Answer getAnswer() {
		String date = ((SimpleDatePicker) widget).getText();

		Answer answer = new Answer();
		answer.add(dbfieldName, tableName, date);
		answer.add(hiddenFields);
		return answer;
	}

	/**
	 * When to focus is lost validate the field.
	 */
	public void onFocus(Widget sender) {
		String name = ((TextBox) widget).getStyleName();
		((SimpleDatePicker) widget).setStyleName(name + "_focus");
	}

	/**
	 * When to focus is lost validate the field.
	 */
	public void onLostFocus(Widget sender) {

		String name = ((TextBox) widget).getStyleName();
		if (name.indexOf("_focus") != -1) {
			((TextBox) widget).setStyleName(name.substring(0, name.length()
					- "_focus".length()));
		}

		if (((SimpleDatePicker) widget).getText().length() > 0) {
			validate();
		}
	}

	/**
	 * Set the value of the date field to the given one.
	 * 
	 * @param message
	 */
	public void setText(String message) {
		((SimpleDatePicker) widget).setText(message);
	}

	/**
	 * Returns the text of the textbox
	 * 
	 * @param message
	 *            The text that is in the textbox
	 */
	public String getText() {
		return ((TextBox) widget).getText();
	}

	/**
	 * Makes this widget display todays date.
	 */
	public void setToToday() {
		Date d = new Date();
		String year = "" + (d.getYear() + 1900);
		String month = "" + (d.getMonth() + 1);
		String day = "" + d.getDate();

		if (month.length() == 1) {
			month = "0" + month;
		}
		if (day.length() == 1) {
			day = "0" + day;
		}

		String fin = year + "-" + month + "-" + day;
		setText(fin);
	}

	public Object clone() {
		DateQuestionComponent d;
		d = new DateQuestionComponent(dbfieldName, tableName, description,
				quantifier, error_msg);
		d.setValidator(this.validator);
		d.setMask(this.mask);
		if (subquestion)
			d.setAsSubQuestion();
		return d;
	}

	/**
	 * Populate this widget with FormData using an Answer object
	 * 
	 * @param answer
	 *            the answer object containing the data.
	 */
	public boolean populate(Answer answer) {

		// if the answer is null do nothing.
		if (answer == null) {
			return false;
		}

		// walking through all the fields-values of answer
		Iterator field_names = answer.getHashMap().keySet().iterator();
		while (field_names.hasNext()) {
			String field_name = (String) field_names.next();

			// if field name matches our widget's field name, use this value
			if (field_name.equalsIgnoreCase(dbfieldName)) {
				String value = (String) answer.getHashMap().get(field_name);

				if (value != null) {
					((SimpleDatePicker) widget).setText(value);

					// apply mask if it exists
					if (mask != null) {
						setText(mask.applyMask(getText()));
					}

					// if we populaeted the widget with nothing, return false.
					if (value != null && value.length() == 0) {
						return false;
					}

					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Populate this widget with FormData
	 */
	public boolean populate() {
		Answer a = FormData.getData(tableName);
		return populate(a);
	}

	/**
	 * Informs observers of change to this widget.
	 */
	private class MyListener implements ClickListener {
		public void onClick(Widget sender) {
			if (((SimpleDatePicker) widget).getText().length() > 0)
				validate();
		}
	}

	/**
	 * The keyboard listener will call the validate method upon every key
	 * entered when the error state is on.
	 * 
	 * @author serge
	 */
	private class ValidationKeyboardListener extends KeyboardListenerAdapter {
		public void onKeyUp(Widget sender, char keyCode, int modifiers) {
			// do validation if neccesary
			validate();

			// apply mask if it exists
			if (mask != null) {
				setText(mask.applyMask(getText()));
			}

			// notify of change
			notifyObservers();
		}
	}

	/**
	 * Set's the textbox's css style.
	 * 
	 * @param style
	 *            the new css style name
	 */
	public void setInnerStyleName(String style) {
		((SimpleDatePicker) widget).setStyleName(style);
	}

	/**
	 * Set's the description's label css style.
	 * 
	 * @param style
	 *            the new css style name
	 */
	public void setDescriptionStyleName(String style) {
		this.description_label.setStyleName(style);
	}

	/**
	 * Sets the width of this textbox
	 * 
	 * @param w
	 *            the new width in pixels
	 */
	public void setWidth(int w) {
		((SimpleDatePicker) widget).setWidth(w + "px");
	}

}
